package com.xysoft.framework.jackson;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.AbstractFactoryBean;

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleSerializers;

public class ModuleFactoryBean extends AbstractFactoryBean<Module> implements BeanNameAware {
	
	private SimpleSerializers serializers = new SimpleSerializers();
	private SimpleDeserializers deserializers = new SimpleDeserializers();
	private Map<Class<?>, Class<?>> mixins;
	private String beanName;

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}

	public void setSerializers(List<JsonSerializer<?>> serializers) {
		for(JsonSerializer<?> serializer : serializers) {
			this.serializers.addSerializer(serializer);
		}
	}

	public void setDeserializers(Map<Class<Object>, JsonDeserializer<Object>> deserializers) {
		for(Entry<Class<Object>, JsonDeserializer<Object>> pair : deserializers.entrySet()) {
			this.deserializers.addDeserializer(pair.getKey(), pair.getValue());
		}
	}

	public void setMixins(Map<Class<?>, Class<?>> mixins) {
		this.mixins = mixins;
	}


	@Override
	public Class<?> getObjectType() {
		return Module.class;
	}

	@Override
	protected Module createInstance() throws Exception {
		return new Module() {
			
			@Override
			public Version version() {
				return Version.unknownVersion();
			}
			
			@Override
			public void setupModule(SetupContext context) {
				if(serializers != null) {
					context.addSerializers(serializers);
				}
				
				if(deserializers != null) {
					context.addDeserializers(deserializers);
				}
				
				if(mixins != null) {
					for(Entry<Class<?>, Class<?>> pair : mixins.entrySet()) {
						context.setMixInAnnotations(pair.getKey(), pair.getValue());
					}
				}
			}
			
			@Override
			public String getModuleName() {
				return beanName;
			}
		};
	}

}
